/**
 * Anderground project - Subway maps processor application.
 * Copyright (C) 2008-2009 Eldar Abusalimov, Ilya Shurigyn
 * 
 * This file is part of Anderground.
 * 
 * Anderground is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * Anderground is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Anderground.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.anderground.core.util;

import org.anderground.core.model.Station;
import org.anderground.core.model.Transition;

/**
 * {@code Binder} helps in building model and monitors it's consistency.
 * <p>
 * <h2>Usage of {@code Binder} in {@link org.anderground.core.model}</h2>
 * <p>
 * One of the {@code Binder}'s purposes is to show, whether a {@link Station} or a
 * {@link Transition} is in use (it means that the object belongs to any model
 * and may be linked with another object). This allows to prevent adding a
 * station to two models at once.<br>
 * {@code Binder} also helps to provide condition observance that two stations belonging
 * to different models cannot be connected by any transition. Check of this
 * condition occurs at each attempt to connect stations by a transition (see
 * {@link Bindable#bindWith(Bindable)}) and if it has failed then a
 * {@link BindingException} is thrown.
 * <p>
 * On the other hand, {@code Binder} can be used for observation over changes in the
 * model, such as objects addition or removal.<br>
 * Suppose you want to remove a station from the model. But you cannot leave any
 * transitions leading to this station in the model. Thus these transitions
 * should be removed too.<br>
 * To trace observance of this condition, each station has a list of the
 * transitions connected with it. At station removal the
 * {@link Bindable#unbindFrom(Binder)} method will be invoked and if there are
 * any transitions bound to this station, all of them will be removed also by an
 * invoking the {@link Bindable#unbindFrom(Binder)} on each of them. This method
 * removes a transition from stations which have been connected with each other
 * by this transition and calls {@link Binder#unbind(Bindable)} method (passing
 * itself to the argument) which completes transition unlinking (this action
 * depends on concrete {@code Binder} implementation). When all transitions of the
 * station have been removed, and station is ready to be unlinked, the
 * {@link Binder#unbind(Bindable)} method is invoked for this station which
 * behaves in the same way as described for a transition removal case.
 * 
 * @see BindingException
 * @see Bindable
 * 
 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
 */
public interface Binder {

	/**
	 * Called when a bindable is being bound to the binder, by either explicit
	 * or implicit request.
	 * 
	 * @param bindable
	 *            the bindable being bound
	 */
	public abstract void bind(Bindable bindable);

	/**
	 * Called when a bindable is being unbound from the binder, by either
	 * explicit or implicit request.
	 * 
	 * @param bindable
	 *            the bindable being unbound
	 */
	public abstract void unbind(Bindable bindable);

	/**
	 * Called at interaction with the objects which behavior depends on model
	 * structure consistency.
	 */
	public abstract void ensureConsistency();

}
